package service

import (
	"common/biz"
	"common/logs"
	"common/net"
	"common/utils"
	"connector/models/request"
	"context"
	"core/dao"
	"core/models/db"
	"core/models/entity"
	"core/repo"
	"encoding/json"
	"errors"
	"fmt"
	"framework/game"
	"framework/msError"
	hall "hall/models/request"
	"hall/models/response"
	"regexp"
	"strconv"
	"time"
)

type UserService struct {
	userDao      *dao.UserDao
	roleDao      *dao.RoleDao
	realDao      *dao.RealDao
	clubDao      *dao.ClubDao
	warehouseDao *dao.WarehouseDao
	typeDao      *dao.TypeDao
	activityDao  *dao.ActivityDao
	confDao      *dao.ConfigDao
	gameDao      *dao.GameDao
	redisDao     *dao.RedisDao
}

func (s *UserService) GetMongoUserInfo(ctx context.Context, uid uint) (*entity.User, error) {
	return s.userDao.MongoFindUserByUid(ctx, uid)
}

func (s *UserService) FindAndSaveUserByUid(ctx context.Context, uid uint, sid uint64, info *request.UserInfo) (*entity.User, error) {
	// 查询mongo 有 返回 没有 mysql和mongo新增
	mongoUser, err := s.GetMongoUserInfo(ctx, uid)
	if err != nil {
		logs.Error("[UserService] MongoFindUserByUid insert user err:%v", err)
		return nil, err
	}
	if mongoUser == nil {
		mongoUser = new(entity.User)
		user, err := s.userDao.FindUserByUid(ctx, uid)
		if err != nil {
			logs.Error("[UserService] FindUserByUid user err:%v", err)
			return nil, err
		}
		if user == nil || user.ID == 0 {
			logs.Error("[UserService] user is null")
			return nil, errors.New("无查询到用户信息")
		}
		if user.Status == 9 {
			return nil, errors.New("该账号已注销")
		}
		if user.Status == -1 {
			return nil, errors.New("帐号已冻结")
		}
		mongoUser.Uid = uid
		mongoUser.Sid = sid
		if user.TransactionPassword != "" {
			mongoUser.IsTranPwd = true
		}
		mongoUser.WalletID = user.WalletId
		mongoUser.MobilePhone = user.Username
		mongoUser.Status = user.Status
		mongoUser.CreateTime = user.CreatedAt
		mongoUser.LastLoginTime = time.Now().UnixMilli()
		mongoUser.InviteCode = user.InviteCode
		mongoUser.BuyCardNum = s.warehouseDao.CardBuyCount(ctx, uid)
		if user.Pid != 0 {
			inviteRole := s.roleDao.FindRoleByRid(ctx, user.Pid)
			if inviteRole != nil {
				mongoUser.InviteMsg.Uid = user.Pid
				mongoUser.InviteMsg.Nickname = inviteRole.Nickname
			}
		}
		if user.RoleID == 0 && info.Nickname != "" {
			//save
			mongoUser.Nickname = info.Nickname
			mongoUser.Avatar = info.Avatar
			role := &db.Role{
				UID:      uid,
				Nickname: info.Nickname,
				Avatar:   info.Avatar,
			}
			role.ID, err = s.roleDao.Insert(ctx, role)
			if err != nil {
				logs.Error("[UserService] Insert role err:%v", err)
				return nil, err
			}
			if err = s.userDao.UpRoleID(ctx, uid, role.ID); err != nil {
				logs.Error("[UserService] UpRoleID user err:%v", err)
				return nil, err
			}
			if err = s.warehouseDao.InitWarehouseInsert(ctx, uid); err != nil {
				logs.Error("[UserService] init warehouse err:%v", err)
				return nil, err
			}
			if err = s.userDao.InitProductionInsert(ctx, uid); err != nil {
				logs.Error("[UserService] init production err:%v", err)
				return nil, err
			}

		} else {
			role := s.roleDao.FindRoleByRid(ctx, uid)
			mongoUser.Nickname = role.Nickname
			mongoUser.Avatar = role.Avatar
			mongoUser.IsVIP = role.IsVIP
			if role.ClubID != 0 {
				club := s.clubDao.FindClubById(ctx, role.ClubID)
				if club != nil {
					mongoUser.ClubMsg.ClubId = role.ClubID
					mongoUser.ClubMsg.ClubName = club.Name
				}
			}
		}
		if user.RealId != 0 {
			userReal := s.realDao.FindRealByUid(ctx, uid)
			mongoUser.RealMsg.Name = userReal.Name
			mongoUser.RealMsg.IDCard = userReal.IDCard
		}

		if err = s.userDao.MongoUserInsert(context.TODO(), mongoUser); err != nil {
			logs.Error("[UserService] FindUserByUid insert user err:%v", err)
			return nil, err
		}
	} else {
		err = s.userDao.MongoUserUpSid(ctx, uid, sid)
		if err != nil {
			logs.Error("[UserService] err=修改socketID失败 dbErr=%v", err)
			return nil, err
		}
	}
	return mongoUser, nil
}

func (s *UserService) FindUserByUid(ctx context.Context, uid uint) (*entity.User, error) {
	user, err := s.userDao.MongoFindUserByUid(ctx, uid)
	if err != nil {
		err = fmt.Errorf("[UserService] FindUserByUid insert user err:%v", err)
		return nil, err
	}
	if user == nil {
		return nil, errors.New("无查询到用户")
	}
	return user, nil
}

func (s *UserService) UpdateUserAddressByUid(uid string, req hall.UpdateUserAddressReq) error {
	//user := &entity.User{
	//	Uid:      uid,
	//	Address:  req.Address,
	//	Location: req.Location,
	//}
	//err := s.userDao.UpdateUserAddressByUid(context.TODO(), user)
	//if err != nil {
	//	logs.Error("userDao.UpdateUserAddressByUid err:%v", err)
	//	return err
	//}
	return nil
}

func (s *UserService) TypeAll(ctx context.Context) *[]db.Type {
	return s.typeDao.All(ctx)
}

func (s *UserService) RealName(ctx context.Context, uid uint, req *hall.UserRealName) *msError.Error {
	//1.查看用户数据
	user, err := s.userDao.FindUserByUid(ctx, uid)
	if err != nil {
		logs.Error("[userHandler]用户%d RealName err:查询用户失败 req=%v,err=%v", uid, req, err)
		return biz.RequestDataError
	}
	if user.RealId > 0 {
		logs.Error("[userHandler]用户%d RealName err:用户已实名 req=%v,err=%v", uid, req, err)
		return biz.SqlError
	}
	//2.验证身份证号姓名
	count := s.realDao.RealCard(ctx, req.IDCard)
	if count > 0 {
		logs.Error("[userHandler]用户%d RealName err:身份证号已存在 req=%v,err=%v", uid, req, err)
		return biz.CardUse
	}
	url := game.Conf.GameConfig["code_config"]["value"].(map[string]any)["url"].(string)
	appcode := game.Conf.GameConfig["code_config"]["value"].(map[string]any)["appcode"].(string)
	body := net.AliyunHttpGetUrl(url, appcode, req.Name, req.IDCard)
	res := make(map[string]any)
	err = json.Unmarshal(body, &res)
	if len(res) == 0 {
		return biz.CardNoError
	}
	if int(res["code"].(float64)) != 0 {
		logs.Error("[userHandler]用户%d RealName err:实名信息解析失败 req=%v,err=%v", uid, res, err)
		return biz.CardError
	}
	//3.添加实名
	realName := &db.UserRealName{
		UID:      uid,
		Name:     req.Name,
		IDCard:   req.IDCard,
		RealBody: string(body),
	}
	realID, errs := s.realDao.AddReal(ctx, realName)
	if errs != nil {
		logs.Error("[userHandler]用户%d RealName err:添加实名失败 req=%v,err=%v", uid, realName, err)
		return biz.SqlError
	}
	//4.修改缓存实名
	realMsg := entity.RealMsg{
		Name:   req.Name,
		IDCard: req.IDCard,
	}
	errs = s.realDao.MongoUpUserReal(ctx, uid, realMsg)
	if errs != nil {
		logs.Error("[userHandler]用户%d RealName err:修改缓存实名失败 req=%v,err=%v", uid, realMsg, err)
		return biz.SqlError
	}
	//5.修改为已实名
	errs = s.userDao.UpRealName(ctx, uid, realID)
	if errs != nil {
		logs.Error("[userHandler]用户%d RealName err:修改为已实名失败 req=%v,err=%v", uid, req, err)
		return biz.SqlError
	}
	return nil
}

func (s *UserService) GetUID(ctx context.Context, token string) uint {
	return s.userDao.GetUID(ctx, token)
}

func (s *UserService) GetUserOfRole(ctx context.Context, uid uint) *db.UserHasOneRole {
	return s.userDao.GetUserOfRole(ctx, uid)
}

func (s *UserService) GetUserOsReal(ctx context.Context, uid uint) *db.UserHasOneRealOfWallet {
	return s.userDao.GetUserOfReal(ctx, uid)
}

func (s *UserService) GetRoleInfo(ctx context.Context, uid uint) *db.Role {
	return s.roleDao.GetRole(ctx, uid)
}

func (s *UserService) GetRole(ctx context.Context, uid uint, types int) (int64, *db.Role) {
	count := s.userDao.GetInviteCount(ctx, uid, types)
	data := s.GetRoleInfo(ctx, uid)
	return count, data
}

//func (s *UserService) ContributeLog(ctx context.Context, uid uint, req *hall.UserContributeLog) (int64, any) {
//	var data any
//	var count int64
//	switch req.Type {
//	case 1:
//		c, res := s.userDao.GetStraightUserLog(ctx, uid, req)
//		row := *res
//		for k, v := range row {
//			row[k].Num, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", v.Num), 64)
//		}
//		data = row
//		count = c
//	case 2:
//		c, res := s.userDao.GetBetweenUserLog(ctx, uid, req)
//		row := *res
//		for k, v := range row {
//			row[k].Num, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", v.Num), 64)
//		}
//		data = row
//		count = c
//	}
//	return count, data
//}

func (s *UserService) ActivityList(ctx context.Context, uid uint) any {
	list := s.activityDao.ActivityList(ctx)
	count := s.userDao.GetInviteCount(ctx, uid, 1)
	data := *list
	for activityKey, activity := range data {
		for conditionKey, condition := range activity.ActivityCondition {
			// 验证条件是否满足
			if count < condition.Condition {
				continue
			}
			isReward := s.activityDao.MongoIsReward(ctx, uid, condition.ActivityID, condition.ID)
			data[activityKey].ActivityCondition[conditionKey].Status = 1
			if isReward {
				data[activityKey].ActivityCondition[conditionKey].Status = 2
			}
			//查看数据,状态改为可领取或已领取
		}
	}
	return &data
}

func (s *UserService) ActivityReceive(ctx context.Context, uid uint, req *hall.ActivityReceive) *msError.Error {
	activity := s.activityDao.GetActivityInfo(ctx, req.ActivityID)
	if activity == nil || activity.ID == 0 {
		logs.Error("[userHandler]用户%d ActivityReceive err:未获取到活动信息 req=%v", uid, req)
		return biz.RequestDataError
	}
	condition := s.activityDao.GetActivityConditionInfo(ctx, req.ActivityID, req.InviteID)
	if condition == nil || condition.ID == 0 {
		logs.Error("[userHandler]用户%d ActivityReceive err:未获取到活动条件信息 req=%v", uid, activity)
		return biz.RequestDataError
	}
	count := s.userDao.GetInviteCount(ctx, uid, 1)
	if count < condition.Condition {
		logs.Error("[userHandler]用户%d ActivityReceive err:当前%d人数,小于条件%d req=%v", uid, count, condition.Condition, condition)
		return biz.ActivityNotReceiveError
	}
	isReceive := s.activityDao.MongoIsReward(ctx, uid, req.ActivityID, req.InviteID)
	if isReceive {
		logs.Error("[userHandler]用户%d ActivityReceive err:已领取 req=%v", uid, condition)
		return biz.ReceiveError
	}
	reward := s.activityDao.GetActivityConditionReward(ctx, req.ActivityID, req.InviteID)
	return s.activityDao.ActivityReceive(ctx, uid, reward)
}

func (s *UserService) ContributeReceive(ctx context.Context, uid uint, req *hall.ContributeReceive) *msError.Error {
	//activity := s.activityDao.GetActivityInfo(ctx, req.ID)
	//if activity == nil || activity.ID == 0 {
	//	logs.Error("[userHandler]用户%d ActivityReceive err:未获取到活动信息 req=%v", uid, req)
	//	return biz.RequestDataError
	//}
	//role := s.roleDao.GetRole(ctx, uid)
	//if req.TypeID == 15 {
	//	if float64(req.Num) > role.IncomeXj {
	//		logs.Error("[userHandler]用户%d ActivityReceive err:领取贡献值%d，小于可领取数量%f req=%v", uid, req.Num, role.IncomeXj, activity)
	//		return biz.BuyNotNumError
	//	}
	//} else {
	//	if float64(req.Num) > role.IncomeXy {
	//		logs.Error("[userHandler]用户%d ActivityReceive err:领取贡献值%d，小于可领取数量%f req=%v", uid, req.Num, role.IncomeXy, activity)
	//		return biz.BuyNotNumError
	//	}
	//}
	//return s.activityDao.ContributeReceive(ctx, uid, req.ID, req.TypeID, req.Num)
	return nil
}

func (s *UserService) GetWalletOfReal(ctx context.Context, uid uint) *db.UserHfWalletHasOneRealName {
	return s.userDao.GetWalletOfReal(ctx, uid)
}

func (s *UserService) UpdateUserCancel(ctx context.Context, uid, status int) error {
	return s.userDao.UpdateUserCancel(ctx, uid, status)
}

//func (s *UserService) UserFriends(ctx context.Context, uid uint) *[]response.Friends {
//	var friends []response.Friends
//	friendList := s.userDao.UserFriends(ctx, uid)
//	for _, v := range *friendList {
//		friends = append(friends, response.Friends{
//			UID:        v.ID,
//			Username:   fmt.Sprintf("%v****%v", v.Username[0:3], v.Username[7:]),
//			Nickname:   v.Role.Nickname,
//			Avatar:     v.Role.Avatar,
//			LevelID:    v.Role.LevelID,
//			CreateTime: v.CreatedAt.Format(time.DateTime),
//		})
//	}
//
//	return &friends
//}

func (s *UserService) UpSid(ctx context.Context, uid uint, sid uint64) error {
	return s.userDao.MongoUserUpSid(ctx, uid, sid)
}

func (s *UserService) MongoGetUser(ctx context.Context, uid uint) (*entity.User, error) {
	return s.userDao.MongoFindUserByUid(ctx, uid)
}

func (s *UserService) GetConfAll(ctx context.Context) *[]db.Config {
	return s.confDao.GetAll(ctx)
}

func (s *UserService) GetBank(ctx context.Context) *[]db.Bank {
	return s.confDao.GetBank(ctx)
}

//func (s *UserService) GetUidByPhone(ctx context.Context, phone string) uint {
//	return s.userDao.GetUidByPhone(ctx, phone)
//}

func (s *UserService) GetVip(ctx context.Context, id uint) *db.VipHasOneReward {
	return s.userDao.GetVipInfo(ctx, id)
}

func (s *UserService) MonthlyCard(ctx context.Context, uid, id uint) (*response.MonthlyCard, *msError.Error) {
	//获取vip信息
	vipInfo := s.GetVip(ctx, id)
	if vipInfo == nil || vipInfo.ID == 0 {
		logs.Error("[userHandler]用户%d MonthlyCard err:未获取到会员卡信息 req=%v", uid, id)
		return nil, biz.RequestDataError
	}
	//组装奖励数据
	reward := make([]response.MonthlyCardReward, 0)
	for _, v := range vipInfo.Reward {
		var totalOutput, output float64
		if v.Types.Type == 1 {
			types := s.typeDao.GetInfo(ctx, 11)
			totalOutput = utils.DecimalIntDiv(v.TypeCard.TotalOutput, types.Val)
			output = utils.DecimalIntDiv(v.VIPReward.Rate, types.Val)
		}
		reward = append(reward, response.MonthlyCardReward{
			TypeID:          v.TypeID,
			TypeName:        v.Types.Name,
			TypeImg:         v.Types.Img,
			Num:             v.Num,
			CardName:        v.Types.Name,
			CardLevel:       v.TypeCard.Level,
			CardTotalOutput: totalOutput,
			CardOutput:      output,
		})
	}
	//查看本人是否拥有该会员卡
	role := s.GetRoleInfo(ctx, uid)
	receiveCount := s.GetVipReceiveCount(ctx, uid, vipInfo.ID, utils.TimeOrDateAsYear(0, "", "Y-m-d"))
	isReceive := false
	if receiveCount > 0 {
		isReceive = true
	}
	var consumeNum float64
	count := s.userDao.GetVipOrderCount(ctx)
	priceOne := s.userDao.GetVipPrice(ctx, count)
	if priceOne.ConsumeTypeID == 11 {
		consumeNum = utils.DecimalIntDiv(priceOne.ConsumeNum, priceOne.Types.Val)
	} else {
		consumeNum = utils.DecimalIntByFloat(priceOne.ConsumeNum)
	}
	info := response.MonthlyCard{
		ID:              vipInfo.ID,
		Name:            vipInfo.Name,
		Info:            vipInfo.Info,
		Type:            vipInfo.Type,
		Img:             vipInfo.Img,
		TotalDay:        vipInfo.Term,
		SurplusDay:      role.VipTerm,
		Price:           vipInfo.Price,
		IsHave:          role.IsVIP,
		Reward:          reward,
		IsReceive:       isReceive,
		ConsumeTypeID:   priceOne.ConsumeTypeID,
		ConsumeTypeName: priceOne.Types.Name,
		ConsumeTypeImg:  priceOne.Types.Img,
		ConsumeNum:      consumeNum,
	}
	return &info, nil
}

func (s *UserService) VipOrderInfo(ctx context.Context, cancel int, uid uint, id uint) *entity.VipOrder {
	return s.userDao.MongoGetOrder(ctx, cancel, uid, id)
}

func (s *UserService) VipCreateOrder(ctx context.Context, order *entity.VipOrder) error {
	return s.userDao.VipCreateOrder(ctx, order)
}

func (s *UserService) VipOrderInfoByOrderNo(ctx context.Context, uid uint, orderNo string) *entity.VipOrder {
	return s.userDao.MongoGetVipOrderByOrderNo(ctx, uid, orderNo)
}

func (s *UserService) VipOrderCancel(ctx context.Context, order *entity.VipOrder) error {
	return s.userDao.VipOrderCancel(ctx, order)
}

func (s *UserService) VipPay(ctx context.Context, order *entity.VipOrder, response string) error {
	return s.userDao.VipOrderPay(ctx, order, response)
}

func (s *UserService) UpdateRole(ctx context.Context, role *db.Role) error {
	return s.userDao.UpdateRole(ctx, role)
}

func (s *UserService) MongoVipOrderAll(ctx context.Context) *[]entity.VipOrder {
	return s.userDao.MongoVipOrderAll(ctx)
}

func (s *UserService) RoleByVip(ctx context.Context) *[]db.Role {
	return s.userDao.RoleByVip(ctx)
}

func (s *UserService) GetVipReceiveCount(ctx context.Context, uid uint, id uint, times string) int64 {
	return s.userDao.GetVipReceiveCount(ctx, uid, id, times)
}

func (s *UserService) VipReceive(ctx context.Context, receive *entity.VipReceive) error {
	return s.userDao.VipReceive(ctx, receive)
}

func (s *UserService) LastSign(ctx context.Context, uid uint) (int64, int64, int64) {
	var round, cumulativeDay, day int64 = 1, 0, -1
	userSign := s.userDao.LastUserSign(ctx, uid)
	if userSign == nil || userSign.SignID == 0 {
		return round, cumulativeDay, day
	}
	//现在的时间-签到时间 大于1天 则重新
	t := time.Now()
	times := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, -1)
	asTime := utils.DateAsTime(fmt.Sprintf("%v 00:00:00", userSign.Dates))
	if times.Unix() > asTime {
		round = userSign.Round + 1
		day = 1
	} else if times.Unix() < asTime {
		round = userSign.Round
		cumulativeDay = userSign.CumulativeDay
		day = userSign.SignDay - 1
	} else {
		round = userSign.Round
		cumulativeDay = userSign.CumulativeDay
		day = userSign.SignDay + 1
	}
	if day > 30 {
		round++
		day -= 30
	}
	return round, cumulativeDay, day
}

func (s *UserService) GetSign(ctx context.Context) *[]db.SignHasOneType {
	data := s.userDao.GetSign(ctx)
	return data
}

func (s *UserService) SignInfo(ctx context.Context, uid, id uint) (*response.EverydaySign, bool) {
	data := s.GetSign(ctx)
	var res response.EverydaySign
	round, cumulativeDay, dates := s.LastSign(ctx, uid)
	res.CumulativeDay = cumulativeDay
	role := s.GetRoleInfo(ctx, uid)
	var receive bool
	for _, v := range *data {
		isCan, isSign, isCondition, isVIPReceive := false, false, false, false
		if (v.Dates == 1 && dates == -1) || v.Dates == dates {
			isCan = true
		}
		userSignCount := s.GetMongoUserSignInfo(ctx, uid, round, v.ID)
		//var userSignDates string
		if userSignCount != nil && userSignCount.UID != 0 {
			isSign = true
			//userSignDates = userSignCount.Dates
		}
		//if role.IsVIP {
		//	if isSign || isCan {
		//		if userSignDates == "" {
		//			userSignDates = utils.TimeOrDateAsYear(0, "", "Y-m-d")
		//		}
		//		vipCount := s.GetVipReceiveCount(ctx, uid, id, userSignDates)
		//		if vipCount <= 0 {
		//			isVIPReceive = true
		//		}
		//	}
		//}
		if isSign {
			isCan = false
			isCondition = false
		}
		if isCan && dates != -1 {
			if role.IsVIP {
				isCondition = true
			} else {
				//TODO 查看今日是否玩过卡牌游戏
				gameCount := s.GetMongoCardLogCount(ctx, uid)
				if gameCount > 0 && v.Dates == dates {
					isCondition = true
				}
			}
		}
		if dates == -1 && v.Dates == 1 {
			isCondition = true
		}
		if (isCondition && isCan) || isVIPReceive {
			receive = true
		}
		res.SignEach = append(res.SignEach, response.SignEach{
			SignID:       v.ID,
			SignDay:      v.Dates,
			TypeID:       v.TypeID,
			TypeImg:      v.Types.Img,
			TypeName:     v.Types.Name,
			Num:          v.Num,
			IsSign:       isSign,
			IsCan:        isCan,
			IsCondition:  isCondition,
			IsVIPReceive: isVIPReceive,
		})
	}
	return &res, receive
}

func (s *UserService) UserSign(ctx context.Context, uid uint, id uint) *msError.Error {
	data := s.GetSign(ctx)
	round, cumulativeDay, dates := s.LastSign(ctx, uid)
	role := s.GetRoleInfo(ctx, uid)
	var info response.SignEach
	for _, v := range *data {
		isCan, isSign, isCondition, isVIPReceive := false, false, false, false
		if (v.Dates == 1 && dates == -1) || v.Dates == dates {
			isCan = true
		}
		userSignCount := s.GetMongoUserSignInfo(ctx, uid, round, v.ID)
		if userSignCount != nil && userSignCount.UID != 0 {
			isSign = true
		}
		//if role.IsVIP {
		//	if isSign {
		//		vipCount := s.GetVipReceiveCount(ctx, uid, id, userSignCount.Dates)
		//		if vipCount <= 0 {
		//			isVIPReceive = true
		//		}
		//	}
		//}
		if isSign {
			isCan = false
			isCondition = false
		}
		if isCan && dates != -1 {
			if role.IsVIP {
				isCondition = true
			} else {
				//TODO 查看今日是否玩过卡牌游戏
				gameCount := s.GetMongoCardLogCount(ctx, uid)
				if gameCount > 0 && v.Dates == dates {
					isCondition = true
				}
			}
		}
		if dates == -1 && v.Dates == 1 {
			isCondition = true
		}
		if isSign {
			if !isVIPReceive {
				continue
			}
		} else {
			if !isCan || !isCondition {
				continue
			}
		}
		info = response.SignEach{
			SignID:       v.ID,
			SignDay:      v.Dates,
			TypeID:       v.TypeID,
			TypeImg:      v.Types.Img,
			TypeName:     v.Types.Name,
			Num:          v.Num,
			IsSign:       isSign,
			IsCan:        isCan,
			IsCondition:  isCondition,
			IsVIPReceive: isVIPReceive,
		}
	}
	if info.SignID == 0 {
		logs.Error("[userHandler]用户%d UserSign err:今日已签到或为满足签到条件 ", uid)
		return biz.SignOrNotConditionError
	}
	UserSignLog := &entity.UserSignLog{
		UID:           uid,
		Round:         round,
		CumulativeDay: cumulativeDay + 1,
		SignID:        info.SignID,
		SignDay:       info.SignDay,
		TypeID:        info.TypeID,
		TypeName:      info.TypeName,
		TypeImg:       info.TypeImg,
		Num:           info.Num,
		Dates:         utils.TimeOrDateAsYear(0, "", "Y-m-d"),
		SignTime:      time.Now().Format(time.DateTime),
	}
	return s.userDao.UserSign(ctx, id, UserSignLog)
}

func (s *UserService) UserSignReceive(ctx context.Context, sign *entity.UserSignLog, vip *entity.VipReceive) *msError.Error {
	return s.userDao.UserSignReceive(ctx, sign, vip)
}

func (s *UserService) MonthlyCardOpen(ctx context.Context, uid uint, id uint) (*db.Role, *msError.Error) {
	role := s.GetRoleInfo(ctx, uid)
	if role == nil || role.ID == 0 {
		logs.Error("[user]用户%d MonthlyCardOpen err:未获取到角色信息 req=%v", uid, role)
		return nil, biz.RequestDataError
	}
	if role.IsVIP {
		logs.Error("[user]用户%d MonthlyCardOpen err:该用户已经是vip，无需购买 req=%v", uid, role)
		return nil, biz.VipNotHave
	}
	vipInfo := s.GetVip(ctx, id)
	if vipInfo == nil || vipInfo.ID == 0 {
		logs.Error("[user]用户%d Receive err:未获取到月卡信息 req=%v", uid, vipInfo)
		return nil, biz.RequestDataError
	}
	var material *db.WarehouseMaterialHasOneType
	count := s.userDao.GetVipOrderCount(ctx)
	priceOne := s.userDao.GetVipPrice(ctx, count)
	if priceOne.ConsumeTypeID != 0 {
		material = s.warehouseDao.GetMaterialInfoByTypeID(ctx, uid, priceOne.ConsumeTypeID)
		if material == nil || material.ID == 0 {
			logs.Error("[user]用户%d Receive err:余额不足 req=%v", uid, material)
			return nil, biz.GoodsPayError
		}
		if material.Num < priceOne.ConsumeNum {
			logs.Error("[user]用户%d Receive err:余额不足 req=%v", uid, material)
			return nil, biz.GoodsPayError
		}
	}
	err := s.userDao.MonthlyCardAdd(ctx, uid, vipInfo, material, priceOne)
	role.IsVIP = true
	role.VipTerm = vipInfo.Term
	return role, err
}

func (s *UserService) GetMongoUserSignInfo(ctx context.Context, uid uint, round int64, id uint) *entity.UserSignLog {
	return s.userDao.GetMongoUserSignInfo(ctx, uid, round, id)
}

func (s *UserService) GetMongoCardLogCount(ctx context.Context, uid uint) int64 {
	return s.gameDao.GetMongoCardLogCount(ctx, uid)
}

func (s *UserService) CheckUser(ctx context.Context, u uint, inviteCode int64) (*response.SelectUser, *msError.Error) {
	uid := s.GetInviteCodeByUid(ctx, inviteCode)
	if uid == 0 {
		return nil, biz.CheckNotUser
	}
	if uid == u {
		return nil, biz.NotMyUser
	}
	userRole := s.GetUserOsReal(ctx, uid)
	if userRole == nil || userRole.ID == 0 {
		return nil, biz.CheckNotUser
	}
	var res response.SelectUser
	res.UID = uid
	res.Nickname = userRole.Role.Nickname
	return &res, nil
}

func (s *UserService) GetInviteCodeByUid(ctx context.Context, inviteCode int64) uint {
	return s.userDao.GetInviteCodeByUid(ctx, inviteCode)
}

func (s *UserService) GetLastUserRewardSum(ctx context.Context, uid uint) int64 {
	sum := s.userDao.MongoGetLastUserRewardSum(ctx, uid)
	types := s.typeDao.GetInfo(ctx, 11)
	sum = utils.DecimalFloatByInt(utils.DecimalIntDiv(sum, types.Val))
	return sum
}

func (s *UserService) GetLastUserReward(ctx context.Context, uid uint, req *hall.PageMsg) (int64, *[]response.LastPullUserReward) {
	count, data := s.userDao.MongoGetLastUserReward(ctx, uid, req)
	var res []response.LastPullUserReward
	for _, v := range *data {
		if v.RewardTypeID == 11 {
			types := s.typeDao.GetInfo(ctx, v.RewardTypeID)
			v.Reward = utils.DecimalFloatByInt(utils.DecimalIntDiv(v.Reward, types.Val))
		}
		userRole := s.GetUserOsReal(ctx, v.UID)
		res = append(res, response.LastPullUserReward{
			Nickname:       userRole.Role.Nickname,
			Avatar:         userRole.Role.Avatar,
			InviteCode:     userRole.InviteCode,
			RewardTypeID:   v.RewardTypeID,
			RewardTypeName: v.RewardTypeName,
			RewardTypeImg:  v.RewardTypeImg,
			RewardNum:      v.Reward,
			IsReceive:      v.IsReceive,
			RewardTime:     v.AddTime,
		})
	}
	return count, &res
}

func (s *UserService) PullActivityReceive(ctx context.Context, uid uint) *msError.Error {
	return s.userDao.PullActivityReceive(ctx, uid)
}

func (s *UserService) PullActivityContribution(ctx context.Context, uid uint, req *hall.UserContribute) (float64, int64, *[]response.ActivityContribution) {
	var data []response.ActivityContribution
	var total float64
	var count int64
	switch req.Type {
	case 1:
		c, res := s.userDao.GetStraightUserLogList(ctx, uid, req.PageMsg)
		for _, v := range *res {
			var num = utils.DecimalIntByFloat(v.Num)
			if v.TypeID == 11 {
				types := s.typeDao.GetInfo(ctx, v.TypeID)
				num = utils.DecimalFloatDiv(num, utils.DecimalIntByFloat(types.Val))
			}
			if !v.IsReceive {
				total = utils.DecimalFloatAdd(total, num)
			}
			data = append(data, response.ActivityContribution{
				Nickname:    v.Nickname,
				Avatar:      v.Avatar,
				LevelID:     v.LevelID,
				InviteCode:  v.InviteCode,
				Num:         num,
				TypeID:      v.TypeID,
				TypeName:    v.TypeName,
				TypeImg:     v.TypeImg,
				IsReceive:   v.IsReceive,
				AddTime:     v.AddTime,
				ReceiveTime: v.ReceiveTime,
			})
		}
		count = c
	case 2:
		c, res := s.userDao.GetBetweenUserLogList(ctx, uid, req.PageMsg)
		for _, v := range *res {
			var num = utils.DecimalIntByFloat(v.Num)
			if v.TypeID == 11 {
				types := s.typeDao.GetInfo(ctx, v.TypeID)
				num = utils.DecimalFloatDiv(num, utils.DecimalIntByFloat(types.Val))
			}
			if !v.IsReceive {
				total = utils.DecimalFloatAdd(total, num)
			}
			data = append(data, response.ActivityContribution{
				Nickname:    v.Nickname,
				Avatar:      v.Avatar,
				LevelID:     v.LevelID,
				InviteCode:  v.InviteCode,
				Num:         num,
				TypeID:      v.TypeID,
				TypeName:    v.TypeName,
				TypeImg:     v.TypeImg,
				IsReceive:   v.IsReceive,
				AddTime:     v.AddTime,
				ReceiveTime: v.ReceiveTime,
			})
		}
		count = c
	}
	return total, count, &data
}

func (s *UserService) PullActivityContributionReceive(ctx context.Context, uid uint, types int) *msError.Error {
	return s.userDao.PullActivityContributionReceive(ctx, uid, types)
}

func (s *UserService) PullActivityFriends(ctx context.Context, uid uint, req *hall.PageMsg) (int64, *[]response.Friends) {
	count, data := s.userDao.PullActivityFriends(ctx, uid, req)
	var res []response.Friends
	for _, v := range *data {
		var username = fmt.Sprintf("%v****%v", v.Username[0:3], v.Username[7:])
		res = append(res, response.Friends{
			Username:   username,
			Nickname:   v.Role.Nickname,
			Avatar:     v.Role.Avatar,
			LevelID:    v.Role.LevelID,
			InviteCode: v.InviteCode,
			CreateTime: v.CreatedAt.Format(time.DateTime),
		})
	}
	return count, &res
}

func (s *UserService) ChamberList(ctx context.Context, page int, size int) (int64, *[]response.Chamber) {
	count, res := s.userDao.ChamberList(ctx, page, size)
	var data []response.Chamber
	for _, v := range *res {
		data = append(data, response.Chamber{
			ID:     v.ID,
			Avatar: v.User.Role.Avatar,
			Name:   v.Name,
			Desc:   v.Desc,
		})
	}
	return count, &data
}

func (s *UserService) ChamberMember(ctx context.Context, id uint, msg hall.PageMsg) (int64, *[]response.ChamberMember) {
	count, res := s.userDao.ChamberMember(ctx, id, msg)
	var data []response.ChamberMember
	for _, v := range *res {
		data = append(data, response.ChamberMember{
			Nickname:   v.User.Role.Nickname,
			Avatar:     v.User.Role.Avatar,
			InviteCode: v.User.InviteCode,
			LevelID:    v.LevelID,
			LevelName:  v.Conf.Name,
			WX:         v.WX,
			QQ:         v.QQ,
		})
	}
	return count, &data
}

func (s *UserService) GetLotteryList(ctx context.Context) *[]response.LotteryList {
	data := s.userDao.GetLotteryList(ctx)
	var res []response.LotteryList
	for _, v := range *data {
		var name, img = v.Name, v.Img
		if !v.Type {
			name = v.Types.Name
			img = v.Types.Img
		}
		res = append(res, response.LotteryList{
			ID:   v.ID,
			Type: v.Type,
			Name: name,
			Img:  img,
			Num:  v.Num,
		})
	}
	return &res
}

func (s *UserService) GetConfInfo(ctx context.Context, name string) string {
	return s.confDao.GetVal(ctx, name)
}

func (s *UserService) GetTypeInfo(ctx context.Context, id uint) *db.Type {
	return s.typeDao.GetInfo(ctx, id)
}

func (s *UserService) Lottery(ctx context.Context, uid uint) (*response.LotteryList, *msError.Error) {
	consumeTypeIDStr := s.GetConfInfo(ctx, "lottery_consume_type_id")
	consumeTypeID, _ := strconv.Atoi(consumeTypeIDStr)
	consumeNumStr := s.GetConfInfo(ctx, "lottery_consume_num")
	consumeNum, _ := strconv.Atoi(consumeNumStr)
	types := s.typeDao.GetInfo(ctx, uint(consumeTypeID))
	data, err := s.userDao.Lottery(ctx, uid, types, int64(consumeNum))
	if err != nil {
		return nil, err
	}
	var name, img = data.Name, data.Img
	if !data.Type {
		name = data.Types.Name
		img = data.Types.Img
	}
	res := response.LotteryList{
		ID:   data.ID,
		Type: data.Type,
		Name: name,
		Img:  img,
		Num:  data.Num,
	}
	return &res, nil
}

func (s *UserService) LotteryLog(ctx context.Context, size int64) *[]response.LotteryLogAll {
	data := s.userDao.LotteryLogAll(ctx, size)
	var res []response.LotteryLogAll
	for _, v := range *data {
		user := s.GetRoleInfo(ctx, v.UID)
		var consumeNum float64
		if v.ConsumeTypeID == 11 {
			types := s.typeDao.GetInfo(ctx, 11)
			consumeNum = utils.DecimalIntDiv(v.ConsumeNum, types.Val)
		} else {
			consumeNum = utils.DecimalIntByFloat(v.ConsumeNum)
		}
		res = append(res, response.LotteryLogAll{
			Nickname:        user.Nickname,
			Avatar:          user.Avatar,
			ConsumeTypeName: v.ConsumeTypeName,
			ConsumeTypeImg:  v.ConsumeTypeImg,
			ConsumeNum:      consumeNum,
			LotteryType:     v.LotteryType,
			LotteryName:     v.LotteryName,
			LotteryImg:      v.LotteryImg,
			LotteryNum:      v.LotteryNum,
			AddTime:         v.AddTime,
		})
	}
	return &res
}

func (s *UserService) Customer(ctx context.Context) *[]db.CustomerService {
	return s.userDao.Customer(ctx)
}

func (s *UserService) SetTransactionPassword(ctx context.Context, uid uint, req *hall.SetPwd) (*entity.User, *msError.Error) {
	if req.Password == "" {
		logs.Error("[userHandler]用户%d SetTransactionPassword err:密码不能为空 req=%v", uid, req)
		return nil, biz.TranPasswordError
	}
	if len(req.Password) != 6 {
		logs.Error("[userHandler]用户%d SetTransactionPassword err:密码长度错误 req=%v", uid, req)
		return nil, biz.TranPasswordError
	}
	regex := regexp.MustCompile("[0-9]")
	passwordCheck := regex.MatchString(req.Password)
	if !passwordCheck {
		logs.Error("[userHandler]用户%d SetTransactionPassword err:密码格式错误 req=%v", uid, req)
		return nil, biz.TranPasswordError
	}
	if req.SmsCode == "" {
		logs.Error("[userHandler]用户%d SetTransactionPassword err:验证码不能为空 req=%v", uid, req)
		return nil, biz.SmsCodeError
	}
	user := s.GetUserOsReal(ctx, uid)
	get := s.redisDao.RGet(ctx, user.Username)
	if get != req.SmsCode {
		logs.Error("[userHandler]用户%d SetTransactionPassword err:验证码错误 req=%v", uid, req)
		return nil, biz.SmsCodeError
	}
	password := req.Password
	md5String := utils.Md5Password(password)
	err := s.userDao.SetTransactionPassword(ctx, uid, md5String)
	if err != nil {
		return nil, err
	}
	mongoUser, _ := s.MongoGetUser(ctx, uid)
	return mongoUser, nil
}

func NewUserService(r *repo.Manager) *UserService {
	return &UserService{
		userDao:      dao.NewUserDao(r),
		roleDao:      dao.NewRoleDao(r),
		realDao:      dao.NewRealDao(r),
		clubDao:      dao.NewClubDao(r),
		warehouseDao: dao.NewWarehouseDao(r),
		typeDao:      dao.NewTypeDao(r),
		activityDao:  dao.NewActivityDao(r),
		confDao:      dao.NewConfigDao(r),
		gameDao:      dao.NewGameDao(r),
		redisDao:     dao.NewRedisDao(r),
	}
}
